package morenoapp.components.conclusion;

import com.jgoodies.binding.adapter.Bindings;
import com.jgoodies.binding.beans.PropertyAdapter;
import com.jgoodies.binding.value.ValueModel;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Vector;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import morenoapp.MorenoApp;
import morenoapp.components.common.HintTextArea;
import morenoapp.components.common.SwingAppPanel;
import morenoapp.components.help.MorenoHelp;
import morenoapp.model.data.MorenoModelData;
import morenoapp.model.data.MorenoModelFace;
import morenoapp.model.view2.MorenoView2Face;
import morenoapp.util.I18N;
import morenoapp.util.MorenoSwing;
import morenoapp.util.MorenoUtil;
import org.apache.commons.io.FileUtils;
import org.jdesktop.application.Action;

/**
 *
 * @author dmitry.mamonov
 */
public class ConclusionMainPanel extends SwingAppPanel {
    JButton buttonPutTemplate;
    JButton buttonExport;
    JComboBox comboResource;
    JScrollPane scrollReport;
    JTextArea textReport;
    public ConclusionMainPanel() {
        super();
        initComponents();
        initBinding();
        initLayout();
    }

    @Override
    protected void initComponents() {
        buttonPutTemplate = new JButton(getActions().get("actionPutTemplate"));

        { //init combo
            comboResource = new JComboBox();
            comboResource.addPopupMenuListener(new PopupMenuListener() {
                @Override
                public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                    if (refreshComboResources() == true) {
                        comboResource.hidePopup();
                        comboResource.showPopup();
                    }
                }

                @Override
                public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                    //pass
                }

                @Override
                public void popupMenuCanceled(PopupMenuEvent e) {
                    //pass
                }

            });
            comboResource.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (comboResource.getSelectedIndex() > 0) {
                        Object selected = comboResource.getSelectedItem();
                        if (selected != null) {
                            String resourceName = selected.toString();
                            insertResource(resourceName);
                            comboResource.setSelectedIndex(0);
                        }
                    }
                }

            });
            refreshComboResources();
        }
        { //init text area
            HintTextArea text = new HintTextArea();
            text.setHint(I18N.get("conclution.hint_for_text"));
            textReport = text;
            scrollReport = new JScrollPane(textReport);
            scrollReport.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        }
        buttonExport = new JButton(getActions().get("actionExport"));
    }

    protected void initBinding() {
        MorenoModelFace model = MorenoApp.getModel();

        ValueModel valueModel = new PropertyAdapter(model, MorenoModelData.PROPERTY_CONCLUSION, true);
        Bindings.bind(textReport, valueModel);
    }

    @Override
    protected void initLayout() {
        FormLayout layout = new FormLayout(
                "3dlu, 300px:grow, 3dlu", //columns
                "3dlu, p, 3dlu, 100px:grow, 3dlu, p, 3dlu"); // rows

        //PanelBuilder builder = new PanelBuilder(layout, new FormDebugPanel()); //debug
        PanelBuilder builder = new PanelBuilder(layout, this);

        // Obtain a reusable constraints object to place components in the grid.
        CellConstraints cc = new CellConstraints();
        int row = 2;
        {
            builder.add(MorenoSwing.line(
                    new JLabel(I18N.get("conclution.caption")),
                    buttonPutTemplate,
                    Box.createHorizontalStrut(10),
                    new JLabel(I18N.get("conclution.put_resource")),
                    comboResource,
                    MorenoHelp.createHelpToolbar(this)),
                    cc.rc(row, 2));
        }
        row += 2;
        {
            builder.add(scrollReport, cc.rc(row, 2, "fill, fill"));
        }
        row += 2;
        {
            builder.add(buttonExport, cc.rc(row, 2, "default, right"));
        }
        builder.getPanel();//commit if needed
    }

    @Action
    public void actionPutTemplate() {
        textReport.append(I18N.getResource("conclution.txt"));
    }

    @Action
    public void actionExport() throws IOException {
        File outDir = null;
        JFileChooser chooser = new JFileChooser(outDir);
        chooser.setDialogTitle(I18N.get("conclition.please_select_dir_to_save_report"));
        File lastSavedReport = MorenoApp.getApplicationData().getLastSavedReportDir();
        if (lastSavedReport != null) {
            chooser.setCurrentDirectory(lastSavedReport);
        } else {
            chooser.setCurrentDirectory(new File("."));
        }
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        chooser.setDialogType(JFileChooser.SAVE_DIALOG);
        chooser.setMultiSelectionEnabled(false);
        if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
            outDir = chooser.getSelectedFile();
        }

        if (outDir != null) {
            String text = MorenoApp.getModel().getConclusion();
            generateReport(outDir, text);
        }
    }

    protected void insertResource(String _resourceName) {
        textReport.insert("{{" + _resourceName + "}}\n", textReport.getCaretPosition());
    }

    protected boolean refreshComboResources() {
        Vector<String> values = new Vector<String>();
        values.add(I18N.get("conclution.select_resource"));
        MorenoView2Face view = MorenoApp.getModel().getView();
        for (int i = 0; i < view.getViewsCount(); i++) {
            values.add(view.getViewName(i));
        }

        DefaultComboBoxModel model = (DefaultComboBoxModel) comboResource.getModel();
        boolean changeMatched = true;
        if (model.getSize() == values.size()) {
            changeMatched = false;
            for (int i = 0; i < values.size(); i++) {
                if (values.get(i).equals(model.getElementAt(i)) == false) {
                    changeMatched = true;
                    break;
                }
            }
        }
        if (changeMatched == true) {
            comboResource.setModel(new DefaultComboBoxModel(values));
        }
        return changeMatched;
    }

    public void generateReport(File outDir, String text) throws IOException {
        if (outDir.exists() == false) {
            if (outDir.mkdirs() == false) {
                throw new IOException("Can't create directories for: " + outDir);
            }
        }
        if (outDir.isFile() == true) {
            throw new IOException("Plese, select directory, not file: " + outDir);
        }

        final String crlf = "\r\n";
        final String resourcePatternRegex = "\\{\\{(.*)\\}\\}";
        final Pattern resourcePattern = Pattern.compile(resourcePatternRegex);
        MorenoModelFace model = MorenoApp.getModel();
        StringBuilder html = new StringBuilder(
                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n" +
                "<HTML>" + crlf +
                "<HEAD>" + crlf +
                "<META HTTP-EQUIV=\"CONTENT-TYPE\" CONTENT=\"text/html; charset=UTF-8\">" + crlf +
                "<TITLE>" + MorenoUtil.escapeForHtml(model.getResearchName()) + "</TITLE>" + crlf +
                "</HEAD>" + crlf +
                "<BODY>" + crlf);
        boolean inOrderedList = false;
        boolean inUnorderedList = false;
        //TODO реализовать экспорт только требоуемых диаграмм , а не всех
        //     доступных как это есть сейчас.
        //Set<String> requiredResources = new HashSet<String>();
        for (String line : text.split("\n")) {
            line = MorenoUtil.escapeForHtml(line.trim());

            //apply caption styles
            if (line.startsWith("!!!") == true) {
                line = "<H3>" + line.substring(3) + "</H3>";
            } else if (line.startsWith("!!") == true) {
                line = "<H2>" + line.substring(2) + "</H2>";
            } else if (line.startsWith("!") == true) {
                line = "<H1>" + line.substring(1) + "</H1>";
            }

            //apply lists styles
            if (line.startsWith("*") || line.startsWith("#")) {
                if (line.startsWith("*")) {
                    if (inUnorderedList == false) {
                        html.append("<UL>\r\n");
                        inUnorderedList = true;
                    }
                }
                if (line.startsWith("#")) {
                    if (inOrderedList == false) {
                        html.append("<OL>\r\n");
                        inOrderedList = true;
                    }
                }
                html.append("<LI>");
                line = line.substring(1).trim();
            } else {
                if (inUnorderedList == true) {
                    html.append("</UL>\r\n");
                    inUnorderedList = false;
                }
                if (inOrderedList == true) {
                    html.append("</OL>\r\n");
                    inOrderedList = false;
                }
            }

            //apply text styles
            line = line.replaceAll("-{5,}", "<HR/>");
            line = line.replaceAll("=(\\S[^=]*\\S)=", "<B>$1</B>");
            line = line.replaceAll("-(\\S[^-]*\\S)-", "<I>$1</I>");

            //check resources
            // черновик кода для подсчёта использованных ресурсов
            //Matcher matcher = resourcePattern.matcher(line);
            //if (matcher.matches()==true){
            //    int groupCount = matcher.toMatchResult().groupCount();
            //    for(int i=0;i<=groupCount;i++){
            //        String groupText = matcher.group(i);
            //        System.out.println("group text: "+groupText);
            //    }
            //}

            line = line.replaceAll(resourcePatternRegex, "<IMG src='res/$1.png' alt='$1'/>");
            if (line.isEmpty() == true) {
                String paragraph = "<P>\r\n";
                if (html.lastIndexOf(paragraph) < html.length() - paragraph.length()) {
                    html.append(paragraph);
                }
            } else {
                html.append(line).append("\r\n");
            }

        }
        html.append("<BODY>" + crlf + "</HTML>");
        System.out.println(html.toString());
        File resourcesDir = new File(outDir, "res");
        resourcesDir.mkdirs();

        //save images for report
        MorenoView2Face view = model.getView();
        int backupCurrentViewIndex = view.getCurrentView();
        for (int i = 0; i < view.getViewsCount(); i++) {
            view.setCurrentView(i);
            BufferedImage img = view.getRenderedView();
            ImageIO.write(img, "PNG", new File(resourcesDir, view.getViewName() + ".png"));
        }
        view.setCurrentView(backupCurrentViewIndex);

        //save report text
        File reportFile = new File(outDir, "report.html");
        FileUtils.writeStringToFile(reportFile, html.toString(), "UTF-8");

        //presave report name for next time
        MorenoApp.getApplicationData().setLastSavedReportDir(outDir);

        //open report in web-browser
        Desktop.getDesktop().browse(reportFile.toURI());
    }

    public static void main(String[] args) throws IOException {
        new ConclusionMainPanel().generateReport(new File("tmp/report"), I18N.getResource("conclution.txt"));
    }

}
